package bhwz.seac3.bl.query;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.function.Function;

import bhwz.seac3.DBServiceManager;
import bhwz.seac3.blservice.datacomputer.PerGamePlayerDataComputeBLService;
import bhwz.seac3.blservice.query.MatchQueryBLService;
import bhwz.seac3.blservice.query.PlayerQueryBLService;
import bhwz.seac3.dbservice.nbadata.HotSpotDBService;
import bhwz.seac3.dbservice.nbadata.PlayerMatchDBService;
import bhwz.seac3.dbservice.nbadata.SaveQueryDBService;
import bhwz.seac3.dbservice.nbadata.SeasonDBService;
import bhwz.seac3.dbservice.nbadata.TeamMatchDBService;
import bhwz.seac3.po.MatchPo;
import bhwz.seac3.po.PlayerActionPicturePo;
import bhwz.seac3.po.PlayerCaculationDataPo;
import bhwz.seac3.po.PlayerGameDataPo;
import bhwz.seac3.po.PlayerPo;
import bhwz.seac3.po.PlayerPortraitPicturePo;
import bhwz.seac3.util.Decomposition;
import bhwz.seac3.util.ListSorter;
import bhwz.seac3.util.ListSorter.SortOrder;
import bhwz.seac3.vo.MatchVo;
import bhwz.seac3.vo.PlayerVo;

public class PlayerQueryBL extends UnicastRemoteObject implements
		PlayerQueryBLService {

	private static final long serialVersionUID = 1L;

	private PerGamePlayerDataComputeBLService cbl;
	private SaveQueryDBService<PlayerPo> pdb;
	private SaveQueryDBService<PlayerGameDataPo> ddb;
	private SaveQueryDBService<PlayerActionPicturePo> apdb;
	private SaveQueryDBService<PlayerPortraitPicturePo> ppdb;
	private SaveQueryDBService<PlayerCaculationDataPo> cddb;
	MatchQueryBLService mbl;

	public PlayerQueryBL(PerGamePlayerDataComputeBLService cbl,
			SaveQueryDBService<PlayerPo> pdb,
			SaveQueryDBService<PlayerGameDataPo> ddb,
			SaveQueryDBService<PlayerActionPicturePo> apdb,
			SaveQueryDBService<PlayerPortraitPicturePo> ppdb,
			SaveQueryDBService<PlayerCaculationDataPo> cddb)
			throws RemoteException {
		super();
		this.cbl = cbl;
		this.pdb = pdb;
		this.ddb = ddb;
		this.apdb = apdb;
		this.ppdb = ppdb;
		this.cddb = cddb;
		mbl=null;
	}
	
	@Override
	public List<PlayerVo> query赛季总数据(String season,
			Function<PlayerVo, Comparable<?>> sortColumn,SortOrder sortOrder) throws Exception {
		return ListSorter.sort(get赛季总数据(season), sortColumn, sortOrder);
		
	}

	@Override
	public List<PlayerVo> query场均数据(String season,
			Function<PlayerVo, Comparable<?>> sortColumn,SortOrder sortOrder) throws Exception {
		return ListSorter.sort(get场均数据(season), sortColumn,sortOrder);
	}

	private List<PlayerVo> get赛季总数据(String season) throws Exception {
		return queryAll(season, vo -> cbl.computePlayerDataAllGame(vo));
	}

	private List<PlayerVo> get场均数据(String season) throws Exception {
		return queryAll(season, vo -> cbl.computePlayerDataPerGame(vo));
	}

	private List<PlayerVo> queryAll(String season,
			Function<PlayerVo, PlayerVo> cmd) throws Exception {
		List<PlayerGameDataPo> data = ddb.queryAll(PlayerGameDataPo.class);
		List<PlayerVo> dataInVo = new ArrayList<>();
		List<PlayerVo> result = new ArrayList<>();
		data.stream().filter(po -> po.get赛季().equals(season))
				.forEach(po -> dataInVo.add(addPo2Vo(po, null)));
		for (PlayerVo vo : dataInVo) {
			result.add(cmd.apply(vo));
		}
		for(PlayerVo vo:result){
			PlayerCaculationDataPo pcdqid=new PlayerCaculationDataPo();
			pcdqid.setName(vo.getName());
			pcdqid.set赛季(season);
			addPo2Vo(cddb.queryById(pcdqid), vo);
		}
		
		for(PlayerVo vo:result){
			PlayerPo ppqid=new PlayerPo();
			ppqid.setName(vo.getName());
			PlayerPo r=pdb.queryById(ppqid);
			addPo2Vo(r,vo);
		}
		return result;
	}

	@Override
	public PlayerVo query赛季总数据ByName(String nameOfPlayer, String season)
			throws Exception {
		return queryById(nameOfPlayer, season,
				vo -> cbl.computePlayerDataAllGame(vo));
	}

	@Override
	public PlayerVo query场均数据ByName(String nameOfPlayer, String season)
			throws Exception {
		return queryById(nameOfPlayer, season,
				vo -> cbl.computePlayerDataPerGame(vo));
	}

	private PlayerVo queryById(String nameOfPlayer, String season,
			Function<PlayerVo, PlayerVo> cmd) throws Exception {
		PlayerGameDataPo queryId = new PlayerGameDataPo();
		queryId.set球员姓名(nameOfPlayer);
		queryId.set赛季(season);
		PlayerGameDataPo data = ddb.queryById(queryId);
		PlayerVo dataInVo = addPo2Vo(data, null);
		
		PlayerCaculationDataPo pcdqid=new PlayerCaculationDataPo();
		pcdqid.setName(nameOfPlayer);
		pcdqid.set赛季(season);
		PlayerCaculationDataPo pcdpo=cddb.queryById(pcdqid);
		addPo2Vo(pcdpo,dataInVo);
		
		PlayerPo pqid = new PlayerPo();
		pqid.setName(nameOfPlayer);
		addPo2Vo(pdb.queryById(pqid), dataInVo);
		
		PlayerActionPicturePo apqid = new PlayerActionPicturePo();
		apqid.setKey(nameOfPlayer);
		PlayerPortraitPicturePo ppqid = new PlayerPortraitPicturePo();
		ppqid.setKey(nameOfPlayer);
		addPo2Vo(apdb.queryById(apqid), ppdb.queryById(ppqid), dataInVo);
		
		PlayerVo result = cmd.apply(dataInVo);
		return result;
	}

	/**
	 * @param po
	 *            could be null
	 * @param vo
	 *            if(vo==null) return new vo
	 * @return
	 */
	public static PlayerVo addPo2Vo(PlayerGameDataPo po, PlayerVo vo) {
		if (vo == null)
			vo = new PlayerVo();
		if (po == null)
			return vo;		
		// PlayerGameDataPo
		vo.setName(po.get球员姓名());
		vo.set先发场数(po.get先发场数());
		vo.set在场时间(po.get在场时间());
		// GameDataPo
		vo.set所属球队(po.get所属球队());
		vo.set所属联盟(po.get所属联盟());
		vo.set赛季(po.get赛季());
		vo.set比赛场数(po.get比赛场数());
		vo.set投篮数(po.get投篮数());
		vo.set罚球数(po.get罚球数());
		vo.set失误数(po.get失误数());
		vo.set断球数(po.get断球数());
		vo.set助攻数(po.get助攻数());
		vo.set盖帽数(po.get盖帽数());
		vo.set犯规数(po.get犯规数());
		vo.set比赛得分(po.get比赛得分());
		vo.set投篮命中数(po.get投篮命中数());
		vo.set三分命中数(po.get三分命中数());
		vo.set三分出手数(po.get三分出手数());
		vo.set罚球命中数(po.get罚球命中数());
		vo.set前场篮板数(po.get前场篮板数());
		vo.set后场篮板数(po.get后场篮板数());
		vo.set所属联盟(po.get所属联盟());
		return vo;
	}

	/**
	 * 
	 * @param po
	 *            could be null
	 * @param vo
	 *            if(vo==null) return new vo
	 * @return
	 */
	public static PlayerVo addPo2Vo(PlayerCaculationDataPo po, PlayerVo vo) {
		if (vo == null)
			vo = new PlayerVo();
		if (po == null)
			return vo;		
		vo.setName(po.getName());
		vo.set赛季(po.get赛季());
		vo.set篮板近五场提升率(po.get篮板近五场提升率());
		vo.set助攻近五场提升率(po.get助攻近五场提升率());
		vo.set得分近五场提升率(po.get得分近五场提升率());
		vo.set篮板率(po.get篮板率());
		vo.set进攻篮板率(po.get进攻篮板率());
		vo.set防守篮板率(po.get防守篮板率());
		vo.set助攻率(po.get助攻率());
		vo.set抢断率(po.get抢断率());
		vo.set盖帽率(po.get盖帽率());
		vo.set失误率(po.get失误率());
		vo.set使用率(po.get使用率());
		return vo;
	}

	/**
	 * @param po
	 *            could be null
	 * @param vo
	 *            if(vo==null) return new vo
	 * @return
	 */
	public static PlayerVo addPo2Vo(PlayerPo po, PlayerVo vo) {
		if (vo == null)
			vo = new PlayerVo();
		if (po == null)
			return vo;		
		// PlayerPo
		vo.setName(po.getName());
		vo.setNumber(po.getNumber());
		vo.setPosition(po.getPosition());
		vo.setHeight(po.getHeight());
		vo.setWeight(po.getWeight());
		vo.setBirth(po.getBirth());
		vo.setAge(po.getAge());
		vo.setExp(po.getExp());
		vo.setSchool(po.getSchool());
		return vo;
	}

	/**
	 * 
	 * @param appo
	 *            could be null
	 * @param pppo
	 *            could be null
	 * @param vo
	 *            if(vo==null) return new vo
	 * @return
	 */
	public static PlayerVo addPo2Vo(PlayerActionPicturePo appo,
			PlayerPortraitPicturePo pppo, PlayerVo vo) {
		if (vo == null)
			vo = new PlayerVo();	
		if (appo != null) {
			vo.setActionPicture(appo.getPicture());
		}
		if (pppo != null) {
			vo.setPortraitPicture(pppo.getPicture());
		}
		return vo;
	}

	@Override
	public List<PlayerVo> query当天球员数据(long date) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<PlayerVo> query赛季总数据(String season) throws Exception {
		// TODO Auto-generated method stub
		return PlayerQueryBLService.super.query赛季总数据(season);
	}

	@Override
	public List<PlayerVo> query场均数据(String season) throws Exception {
		// TODO Auto-generated method stub
		return PlayerQueryBLService.super.query场均数据(season);
	}
	
	private void matchDBInit(){
		SaveQueryDBService<MatchPo> sqdb=DBServiceManager.getMatchDBService();
		PlayerMatchDBService pm=DBServiceManager.getPlayerMatchDBService();
		TeamMatchDBService pmd=DBServiceManager.geTeamMatchDBService();
		HotSpotDBService hdb=DBServiceManager.getHotSpotDBService();
		try {
			mbl=new MatchQueryBL(sqdb,pm,pmd,hdb);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	@Override
	public List<PlayerVo> query每场比赛表现(String season, PlayerVo player)
			throws Exception {
		// TODO Auto-generated method stub
		
        if(mbl==null){
            matchDBInit();        	
        }
        
        String playerName=player.getName();
        List<MatchVo> matchList=mbl.queryByPlayer(playerName, season);
        List<PlayerVo> playerList=new LinkedList<PlayerVo>();
        Decomposition d=new Decomposition();
        Iterator<MatchVo> itor=matchList.iterator();
        Queue<PlayerVo> five=new LinkedList<PlayerVo>();
        Queue<PlayerVo> rest=new LinkedList<PlayerVo>();
        while(itor.hasNext()){
        	MatchVo temp=itor.next();
        	playerList.add(d.mtop(temp,player,five,rest));
        }
		return playerList;
	}

	@Override
	public List<PlayerVo> query各个赛季表现(PlayerVo player) throws Exception {
		List<PlayerVo> list=new LinkedList<PlayerVo>();
        SeasonDBService sdb=DBServiceManager.getSeasonDBService();
        PlayerPo ppo=new PlayerPo();
        ppo.setName(player.getName());
        List<String> seasons=sdb.queryJoinedSeasons(ppo);
        Iterator<String> itor=seasons.iterator();
        while(itor.hasNext()){
           String season=itor.next();
           PlayerVo vo=query场均数据ByName(player.getName(), season);
           list.add(vo);
        }
		return list;
	}

	@Override
	public List<PlayerVo> query所有球员赛季表现四分位数(String season,
			Function<PlayerVo, Comparable<?>> sortColumn) throws Exception {
		// TODO Auto-generated method stub
		return PlayerQueryBLService.super.query所有球员赛季表现四分位数(season, sortColumn);
	}
	
	

}
